package com.momo.service.async;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.momo.common.error.RedisKeyEnum;
import com.momo.common.req.sysSetting.authority.AclModuleReq;
import com.momo.common.req.sysSetting.authority.AclReq;
import com.momo.common.req.sysSetting.authority.RoleReq;
import com.momo.common.util.RedisUtil;
import com.momo.mapper.dataobject.AclDO;
import com.momo.mapper.dataobject.AclModuleDO;
import com.momo.mapper.dataobject.RoleAclDO;
import com.momo.mapper.dataobject.RoleDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

/**
 * Created by MOMO on 2019/3/22.
 * 权限模块和权限点异步缓存
 */
@Service
@Slf4j
public class AclAsync {
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 异步 为角色授权权限 --》 redis
     *
     * @param roleId
     * @param aclIdList
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> roleAclsToRedis(Long roleId, List<RoleAclDO> aclIdList) {
        //key 权限类型  v 权限点id
        Multimap<Long, Long> multiMap = ArrayListMultimap.create();
        Set<Long> set = Sets.newHashSet();
        aclIdList.forEach(roleAclDO -> {
            multiMap.put(roleAclDO.getSysAclPermissionType(), roleAclDO.getSysAclId());
            set.add(roleAclDO.getSysAclPermissionType());
        });
        Map<String, String> map = Maps.newHashMap();
        set.forEach(aLong -> {
            List<Long> longs = (List<Long>) multiMap.get(aLong);
            if (!CollectionUtils.isEmpty(longs)) {
                map.put(String.valueOf(aLong), JSONObject.toJSONString(longs));
            }
        });
        redisUtil.hsetputAll(RedisKeyEnum.REDIS_ROLE_ACLS_MAP.getKey() + roleId, map);
        return new AsyncResult<>("为角色授权权限 --》 redis");
    }

    /**
     * 异步 为用户授权角色 --》 redis
     *
     * @param roleId
     * @param acls
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> userRolesToRedis(Long roleId, List<Long> acls) {
        redisUtil.set(RedisKeyEnum.REDIS_USER_ROLES_STR.getKey() + roleId, JSONObject.toJSONString(acls));
        return new AsyncResult<>("为用户授权角色 --》 redis");
    }

    /**
     * 异步 普通角色 --》 redis
     *
     * @param roleDO
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> roleToRedis(RoleDO roleDO) {
        RoleReq.RoleReqRedis roleReqRedis = RoleReq.roleReqRedis(roleDO);
        //角色的类型，0：管理员角色，1：普通用户 2其他
        if ("0".equals(roleDO.getSysRoleType())){
            Map<String,String> role= Maps.newHashMap();
            role.put(RedisKeyEnum.REDIS_ADMIN_ROLE_STR.getKey() + String.valueOf(roleReqRedis.getGroupId()), JSONObject.toJSONString(roleReqRedis));
            role.put(RedisKeyEnum.REDIS_ROLE_STR.getKey() + String.valueOf(roleReqRedis.getId()), JSONObject.toJSONString(roleReqRedis));
            redisUtil.multiSet(role);
        }else {
            redisUtil.set(RedisKeyEnum.REDIS_ROLE_STR.getKey() + String.valueOf(roleReqRedis.getId()), JSONObject.toJSONString(roleReqRedis));
        }
        return new AsyncResult<>("异步 普通角色 --》 redis");
    }
    /**
     * 异步 批量普通角色 --》 redis
     *
     * @param commonRole
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> commonRole(Map<String,String> commonRole) {
        redisUtil.multiSet(commonRole);
        return new AsyncResult<>("异步 批量普通角色 --》 redis");
    }
    /**
     * 异步 批量管理员角色 --》 redis
     *
     * @param adminRole
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> adminRole(Map<String,String> adminRole) {
        redisUtil.multiSet(adminRole);
        return new AsyncResult<>("异步 批量管理员角色 --》 redis");
    }


    /**
     * 异步权限点 --》 redis
     *
     * @param aclModuleDO
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> aclToRedis(AclDO aclModuleDO) {
        AclReq.AclReqRedis aclReq = AclReq.aclRedis(aclModuleDO);
        String str=JSONObject.toJSONString(aclReq);
        redisUtil.hset(RedisKeyEnum.REDIS_ACL_MAP.getKey() + aclModuleDO.getSysAclPermissionType(), String.valueOf(aclModuleDO.getId()),str );
        redisUtil.set(RedisKeyEnum.REDIS_ACL_OBJ.getKey()+aclModuleDO.getId(),str);
        return new AsyncResult<>("异步权限点 --》 redis");
    }

    /**
     * 异步批量权限点 --》 redis
     *
     * @param aclModuleList
     * @param sysAclPermissionType
     * @return
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> batchAclToRedis(List<AclDO> aclModuleList, Long sysAclPermissionType) {
        if (CollectionUtils.isEmpty(aclModuleList)) {
            return new AsyncResult<>("异步批量权限点 --》 redis");
        }
        Map<String, String> map = Maps.newHashMap();
        Map<String, String> mapObj = Maps.newHashMap();
        aclModuleList.forEach(aclModuleDO -> {
            AclReq.AclReqRedis aclReq = AclReq.aclRedis(aclModuleDO);
            String str=JSONObject.toJSONString(aclReq);
            map.put(String.valueOf(aclReq.getId()),str );
            mapObj.put(RedisKeyEnum.REDIS_ACL_OBJ.getKey()+aclReq.getId(),str);
        });
        redisUtil.hsetputAll(RedisKeyEnum.REDIS_ACL_MAP.getKey() + sysAclPermissionType, map);
        redisUtil.multiSet(mapObj);
        return new AsyncResult<>("异步批量权限点 --》 redis");
    }

    /**
     * 异步权限模块 --》 redis
     *
     * @param aclModuleDO
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> aclModuleToRedis(AclModuleDO aclModuleDO) {
        AclModuleReq.AclModuleReqRedis aclModuleReq = AclModuleReq.aclModuleRedis(aclModuleDO);
        redisUtil.hset(RedisKeyEnum.REDIS_ACL_MODULE_MAP.getKey() + aclModuleDO.getSysAclPermissionType(), String.valueOf(aclModuleDO.getId()), JSONObject.toJSONString(aclModuleReq));
        redisUtil.set(RedisKeyEnum.REDIS_ACL_MODULE_OBJ.getKey()+aclModuleDO.getId(),JSONObject.toJSONString(aclModuleReq));
        return new AsyncResult<>("异步权限模块 --》 redis");
    }

    /**
     * 异步批量权限模块 --》 redis
     *
     * @param aclModuleList
     * @param sysAclPermissionType
     */
    @Async("threadPoolTaskExecutor")
    public Future<String> batchAclModuleToRedis(List<AclModuleDO> aclModuleList, Long sysAclPermissionType) {
        if (CollectionUtils.isEmpty(aclModuleList)) {
            return new AsyncResult<>("异步批量权限模块 --》 redis");
        }
        Map<String, String> map = Maps.newHashMap();
        Map<String, String> mapObj = Maps.newHashMap();
        aclModuleList.forEach(aclModuleDO -> {
            AclModuleReq.AclModuleReqRedis aclModuleReq = AclModuleReq.aclModuleRedis(aclModuleDO);
            String str=JSONObject.toJSONString(aclModuleReq);
            map.put(String.valueOf(aclModuleReq.getId()), str);
            mapObj.put(RedisKeyEnum.REDIS_ACL_MODULE_OBJ.getKey()+aclModuleReq.getId(), str);
        });
        redisUtil.hsetputAll(RedisKeyEnum.REDIS_ACL_MODULE_MAP.getKey() + sysAclPermissionType, map);
        redisUtil.multiSet(mapObj);
        return new AsyncResult<>("异步批量权限模块 --》 redis");
    }


}
